using System;
using System.Linq;
using GZ.DB.Entity.wcs_hy;
using GZ.DB.IRepository.wcs_hy;
using GZ.DB.Repository.wcs_hy;

namespace GZ.Projects.WCS_HY
{
    /// <summary>
    /// 双工位处理结果
    /// </summary>
    public class DoubleStackResult
    {
        public bool IsSuccess { get; set; }
        public string Message { get; set; }
    }

    /// <summary>
    /// 双工位堆垛机异常和重分处理类
    /// 专门处理1号机双工位的所有逻辑
    /// </summary>
    public class DoubleStackResend
    {
        private Conn Conn = new Conn();

        /// <summary>
        /// 处理1号机双工位异常
        /// </summary>
        /// <param name="num">堆垛机编号</param>
        /// <returns>处理结果</returns>
        public DoubleStackResult HandleDualStationAlarm(string num)
        {
            string msg = $"\r\n[{num}号双工位堆垛机异常处理开始]{DateTime.Now:yyyy/MM/dd HH:mm:ss}";
            bool isSuccess = true;

            try
            {
                string suffixName = $"TC{num}";
                
                // 获取双工位业务信号
                string plcBusines1 = Conn.HYRedis.GetValue($"{suffixName}.plc_busines1");
                string plcBusines1Last = Conn.HYRedis.GetValue($"{suffixName}.plc_busines1_LAST");
                string plcBusines2 = Conn.HYRedis.GetValue($"{suffixName}.plc_busines2");
                string plcBusines2Last = Conn.HYRedis.GetValue($"{suffixName}.plc_busines2_LAST");

                msg += $"\r\n\t工位1状态：当前[{plcBusines1}]，旧值[{plcBusines1Last}]";
                msg += $"\r\n\t工位2状态：当前[{plcBusines2}]，旧值[{plcBusines2Last}]";

                // 检查工位1是否有异常
                if (plcBusines1 != plcBusines1Last && plcBusines1Last == "0" && plcBusines1 != "0")
                {
                    var station1Result = HandleStationAlarm(suffixName, "S1", plcBusines1, num);
                    msg += station1Result.Message;
                    if (!station1Result.IsSuccess)
                    {
                        isSuccess = false;
                    }
                }

                // 检查工位2是否有异常
                if (plcBusines2 != plcBusines2Last && plcBusines2Last == "0" && plcBusines2 != "0")
                {
                    var station2Result = HandleStationAlarm(suffixName, "S2", plcBusines2, num);
                    msg += station2Result.Message;
                    if (!station2Result.IsSuccess)
                    {
                        isSuccess = false;
                    }
                }

                // 如果两个工位都没有新的异常
                if ((plcBusines1 == plcBusines1Last || plcBusines1Last != "0") && 
                    (plcBusines2 == plcBusines2Last || plcBusines2Last != "0"))
                {
                    msg += $"\r\n\t双工位堆垛机无新异常或重分信号已反馈";
                }

                return new DoubleStackResult { IsSuccess = isSuccess, Message = msg };
            }
            catch (Exception ex)
            {
                msg += $"\r\n\t[Error]双工位异常处理失败：{ex}";
                return new DoubleStackResult { IsSuccess = false, Message = msg };
            }
        }

        /// <summary>
        /// 处理1号机双工位重分标记
        /// </summary>
        /// <param name="num">堆垛机编号</param>
        /// <returns>处理结果</returns>
        public DoubleStackResult HandleDualStationResend(string num)
        {
            string msg = $"\r\n[{num}号双工位堆垛机重分处理开始]{DateTime.Now:yyyy/MM/dd HH:mm:ss}";
            bool isSuccess = true;

            try
            {
                string suffixName = $"TC{num}";
                
                // 获取设备状态
                string modeValue = Conn.HYRedis.GetValue($"{suffixName}.plc_auto"); //设备模式 1 联机自动;2手动;3半自动;4维修;
                string stateValue = Conn.HYRedis.GetValue($"{suffixName}.plc_state");//1正常 允许下发任务
                string loadedValue1 = Conn.HYRedis.GetValue($"{suffixName}.plc_loaded1");//工位1载货台有无货物 1有货 0 无货
                string loadedValue2 = Conn.HYRedis.GetValue($"{suffixName}.plc_loaded2");//工位2载货台有无货物 1有货 0 无货

                // 获取重分标记
                string memResendS1 = Conn.HYRedis.GetValue($"MEM.{suffixName}_S1_Resend");
                string memResendS2 = Conn.HYRedis.GetValue($"MEM.{suffixName}_S2_Resend");

                msg += $"\r\n\t设备状态：模式[{modeValue}]，状态[{stateValue}]";
                msg += $"\r\n\t载货台状态：工位1[{loadedValue1}]，工位2[{loadedValue2}]";
                msg += $"\r\n\t重分标记：工位1[{memResendS1}]，工位2[{memResendS2}]";

                // 检查工位1重分
                if (memResendS1 == "1")
                {
                    var s1Result = HandleStationResend(suffixName, "S1", modeValue, stateValue, loadedValue1, num);
                    msg += s1Result.Message;
                    if (!s1Result.IsSuccess)
                    {
                        isSuccess = false;
                    }
                }

                // 检查工位2重分
                if (memResendS2 == "1")
                {
                    var s2Result = HandleStationResend(suffixName, "S2", modeValue, stateValue, loadedValue2, num);
                    msg += s2Result.Message;
                    if (!s2Result.IsSuccess)
                    {
                        isSuccess = false;
                    }
                }

                // 如果两个工位都没有重分标记
                if (memResendS1 != "1" && memResendS2 != "1")
                {
                    msg += $"\r\n\t双工位堆垛机无重分标记";
                }

                return new DoubleStackResult { IsSuccess = isSuccess, Message = msg };
            }
            catch (Exception ex)
            {
                msg += $"\r\n\t[Error]双工位重分处理失败：{ex}";
                return new DoubleStackResult { IsSuccess = false, Message = msg };
            }
        }

        /// <summary>
        /// 处理指定工位的异常
        /// </summary>
        /// <param name="suffixName">设备名称</param>
        /// <param name="stationNo">工位号(S1/S2)</param>
        /// <param name="alarmCode">报警代码</param>
        /// <param name="num">堆垛机编号</param>
        /// <returns>处理结果</returns>
        private DoubleStackResult HandleStationAlarm(string suffixName, string stationNo, string alarmCode, string num)
        {
            string msg = $"\r\n\t[{stationNo}工位异常处理]";
            bool isSuccess = true;

            try
            {
                // 解析异常类型
                string stackErrMsg = GetAlarmMessage(alarmCode, num, stationNo);
                msg += $"\r\n\t\t异常信息：{stackErrMsg}";

                // 获取当前工位的任务号
                string deviceTaskNo = Conn.HYRedis.GetValue($"{suffixName}.wcs_task_{stationNo}");
                msg += $"\r\n\t\t当前工位任务号：{deviceTaskNo}";

                // 查找对应的堆垛机任务
                IStackerTaskRepository stackerRepo = new StackerTaskRepository();
                StackerTaskEntity stackerTask = stackerRepo.FindList(t =>
                    (t.TaskState == "Doing" || t.TaskState == "Send" || t.TaskState == "Error") &&
                    t.DeviceNo == suffixName &&
                    t.DeviceTaskNo == deviceTaskNo)
                    .OrderByDescending(t => t.CreateTime)
                    .FirstOrDefault();

                if (stackerTask != null)
                {
                    msg += $"\r\n\t\t找到对应任务：{stackerTask.TaskNo}";

                    // 根据异常类型进行处理
                    if (alarmCode == "1" || alarmCode == "3") // 放货有货或放货阻塞
                    {
                        var reallocateResult = HandleReallocateAlarm(stackerTask, stationNo, stackErrMsg, suffixName);
                        msg += reallocateResult.Message;
                        if (!reallocateResult.IsSuccess)
                        {
                            isSuccess = false;
                        }
                    }
                    else if (alarmCode == "2" || alarmCode == "4") // 取货无货或取货阻塞
                    {
                        var cancelResult = HandleCancelAlarm(stackerTask, stationNo, stackErrMsg, num);
                        msg += cancelResult.Message;
                        if (!cancelResult.IsSuccess)
                        {
                            isSuccess = false;
                        }
                    }
                    else
                    {
                        msg += $"\r\n\t\t未知异常类型[{alarmCode}]，需要人工处理";
                        isSuccess = false;
                    }
                }
                else
                {
                    msg += $"\r\n\t\t未找到对应的堆垛机任务，可能任务已完成或不存在";
                }

                return new DoubleStackResult { IsSuccess = isSuccess, Message = msg };
            }
            catch (Exception ex)
            {
                msg += $"\r\n\t\t[Error]{stationNo}工位异常处理失败：{ex}";
                return new DoubleStackResult { IsSuccess = false, Message = msg };
            }
        }

        /// <summary>
        /// 处理指定工位的重分
        /// </summary>
        private DoubleStackResult HandleStationResend(string suffixName, string stationNo, string modeValue, 
            string stateValue, string loadedValue, string num)
        {
            string msg = $"\r\n\t[{stationNo}工位重分处理]";
            bool isSuccess = true;

            try
            {
                // 查找重分状态的任务
                IStackerTaskRepository stackerRepo = new StackerTaskRepository();
                StackerTaskEntity stackerTask = stackerRepo.FindList(t => 
                    t.TaskState == "Reallocate" && 
                    t.DeviceNo == suffixName)
                    .OrderByDescending(t => t.CreateTime)
                    .FirstOrDefault();

                if (stackerTask != null)
                {
                    msg += $"\r\n\t\t找到重分任务：{stackerTask.TaskNo}";

                    // 检查设备状态是否满足重分条件
                    if (modeValue == "1" && stateValue == "1" && loadedValue == "1")
                    {
                        // 等待上位系统给出新的目标地址
                        if (HasNewTargetAddress(stackerTask))
                        {
                            // 执行重分任务下发
                            var resendResult = ExecuteResendTask(stackerTask, stationNo, suffixName, num);
                            msg += resendResult.Message;
                            if (!resendResult.IsSuccess)
                            {
                                isSuccess = false;
                            }
                        }
                        else
                        {
                            msg += $"\r\n\t\t等待上位系统分配新的目标地址";
                        }
                    }
                    else
                    {
                        msg += $"\r\n\t\t设备状态不满足重分条件：模式[{modeValue}]，状态[{stateValue}]，载货台[{loadedValue}]";
                    }
                }
                else
                {
                    msg += $"\r\n\t\t未找到重分状态的任务";
                    // 清除重分标记
                    bool clearResult = Conn.HYRedis.SetValue($"MEM.{suffixName}_{stationNo}_Resend", "0", "MEMQueue");
                    if (clearResult)
                    {
                        msg += $"\r\n\t\t已清除{stationNo}工位重分标记";
                    }
                }

                return new DoubleStackResult { IsSuccess = isSuccess, Message = msg };
            }
            catch (Exception ex)
            {
                msg += $"\r\n\t\t[Error]{stationNo}工位重分处理失败：{ex}";
                return new DoubleStackResult { IsSuccess = false, Message = msg };
            }
        }

        /// <summary>
        /// 处理重分异常（放货有货、放货阻塞）
        /// </summary>
        private DoubleStackResult HandleReallocateAlarm(StackerTaskEntity stackerTask, string stationNo, string stackErrMsg, string suffixName)
        {
            string msg = $"\r\n\t\t[{stationNo}重分处理]";
            bool isSuccess = true;

            try
            {
                // 向WMS申请新货位
                SystemSynchronizationEntity systemSynchronization = new SystemSynchronizationEntity();
                systemSynchronization.syn_direction = 1;
                systemSynchronization.syn_status = 0;
                systemSynchronization.ope_type = "2";
                systemSynchronization.task_no = stackerTask.TaskNo;
                systemSynchronization.ope_time = DateTime.Now;
                systemSynchronization.cur_pos = stackerTask.ToLocalNo;
                systemSynchronization.ope_type = "CF";

                DBOpeation dbo = new DBOpeation();
                bool result = dbo.SystemSynchronizationInsert(systemSynchronization, out string eMsg);

                if (result)
                {
                    // 设置重分信号
                    bool redisResult = Conn.HYRedis.SetValue($"MEM.{suffixName}_{stationNo}_Resend", "1", "MEMQueue");
                    if (redisResult)
                    {
                        msg += $"\r\n\t\t[{stackErrMsg}]重分信号已标记，等待上位系统分配新货位";
                    }
                    else
                    {
                        msg += $"\r\n\t\t[{stackErrMsg}]重分信号标记失败";
                        isSuccess = false;
                    }
                }
                else
                {
                    msg += $"\r\n\t\t[{stackErrMsg}]接口信息插入失败：{eMsg}";
                    isSuccess = false;
                }

                return new DoubleStackResult { IsSuccess = isSuccess, Message = msg };
            }
            catch (Exception ex)
            {
                msg += $"\r\n\t\t[Error]重分处理异常：{ex}";
                return new DoubleStackResult { IsSuccess = false, Message = msg };
            }
        }

        /// <summary>
        /// 处理取消异常（取货无货、取货阻塞）
        /// </summary>
        private DoubleStackResult HandleCancelAlarm(StackerTaskEntity stackerTask, string stationNo, string stackErrMsg, string num)
        {
            string msg = $"\r\n\t\t[{stationNo}取消处理]";
            bool isSuccess = true;

            try
            {
                // 发送取消任务信号
                StackerSendToRedis sendToRedis = new StackerSendToRedis();
                bool sendResult = sendToRedis.ClearTask_DoubleStation(num, "12", "8", "8", out string eMsg);

                if (sendResult)
                {
                    // 清除MEM任务信息
                    StackMemTaskInfo("0", "0", "0", "0", num);
                    msg += $"\r\n\t\t[{stackErrMsg}]任务取消信号已发送，MEM信息已清除";
                }
                else
                {
                    msg += $"\r\n\t\t[{stackErrMsg}]任务取消信号发送失败：{eMsg}";
                    isSuccess = false;
                }

                return new DoubleStackResult { IsSuccess = isSuccess, Message = msg };
            }
            catch (Exception ex)
            {
                msg += $"\r\n\t\t[Error]取消处理异常：{ex}";
                return new DoubleStackResult { IsSuccess = false, Message = msg };
            }
        }

        /// <summary>
        /// 检查是否有新的目标地址
        /// </summary>
        private bool HasNewTargetAddress(StackerTaskEntity stackerTask)
        {
            try
            {
                // 检查任务的目标地址是否已更新
                // 简单的检查：如果ToLocalNo不为空且不是原来的货位，则认为有新地址
                if (!string.IsNullOrEmpty(stackerTask.ToLocalNo) &&
                    stackerTask.ToLocalNo != "0" &&
                    stackerTask.LastUpdatedTime > stackerTask.CreateTime.AddMinutes(1)) // 更新时间晚于创建时间1分钟以上
                {
                    return true;
                }

                return false;
            }
            catch (Exception ex)
            {
                Conn.HYLog.Error(1, "检查新目标地址失败", 1, ex.ToString());
                return false;
            }
        }

        /// <summary>
        /// 执行重分任务下发
        /// </summary>
        private DoubleStackResult ExecuteResendTask(StackerTaskEntity stackerTask, string stationNo,
            string suffixName, string num)
        {
            string msg = $"\r\n\t\t[{stationNo}重分任务下发]";
            bool isSuccess = true;

            try
            {
                // 根据工位确定任务类型
                string taskType = DetermineTaskType(stationNo, stackerTask);

                StackerSendToRedis sendToRedis = new StackerSendToRedis();
                bool result = false;
                string eMsg = "";

                // 根据工位发送相应的任务
                if (stationNo == "S1")
                {
                    // 工位1重分任务
                    result = sendToRedis.SendTask_SingleStation(taskType, stackerTask, out eMsg);
                }
                else if (stationNo == "S2")
                {
                    // 工位2重分任务 - 这里需要根据实际情况调整
                    result = sendToRedis.SendTask_SingleStation(taskType, stackerTask, out eMsg);
                }

                if (result)
                {
                    msg += $"\r\n\t\t{stationNo}工位重分任务下发成功，新目标地址：{stackerTask.ToLocalNo}";

                    // 更新任务状态
                    stackerTask.TaskState = "Send";
                    stackerTask.LastUpdatedTime = DateTime.Now;

                    DBOpeation dbOpeation = new DBOpeation();
                    bool dbResult = dbOpeation.UpdateStackerTask(stackerTask, out string dbError);

                    if (dbResult)
                    {
                        // 清除重分标记
                        bool clearResult = Conn.HYRedis.SetValue($"MEM.{suffixName}_{stationNo}_Resend", "0", "MEMQueue");
                        if (clearResult)
                        {
                            msg += $"\r\n\t\t已清除{stationNo}工位重分标记";
                        }
                        else
                        {
                            msg += $"\r\n\t\t清除{stationNo}工位重分标记失败";
                            isSuccess = false;
                        }
                    }
                    else
                    {
                        msg += $"\r\n\t\t更新任务状态失败：{dbError}";
                        isSuccess = false;
                    }
                }
                else
                {
                    msg += $"\r\n\t\t{stationNo}工位重分任务下发失败：{eMsg}";
                    isSuccess = false;
                }

                return new DoubleStackResult { IsSuccess = isSuccess, Message = msg };
            }
            catch (Exception ex)
            {
                msg += $"\r\n\t\t[Error]重分任务下发异常：{ex}";
                return new DoubleStackResult { IsSuccess = false, Message = msg };
            }
        }

        /// <summary>
        /// 获取异常信息描述
        /// </summary>
        private string GetAlarmMessage(string alarmCode, string num, string stationNo)
        {
            switch (alarmCode)
            {
                case "1":
                    return $"[{num}号堆垛机{stationNo}工位放货有货]";
                case "2":
                    return $"[{num}号堆垛机{stationNo}工位取货无货]";
                case "3":
                    return $"[{num}号堆垛机{stationNo}工位放货阻塞]";
                case "4":
                    return $"[{num}号堆垛机{stationNo}工位取货阻塞]";
                default:
                    return $"[{num}号堆垛机{stationNo}工位未知异常]";
            }
        }

        /// <summary>
        /// 确定任务类型
        /// </summary>
        private string DetermineTaskType(string stationNo, StackerTaskEntity stackerTask)
        {
            // 根据工位和任务类型确定发送的任务类型代码
            if (stationNo == "S1")
            {
                return "9"; // 工位1重分任务
            }
            else if (stationNo == "S2")
            {
                return "10"; // 工位2重分任务（假设的代码，需要根据实际协议调整）
            }

            return "9"; // 默认返回工位1重分
        }

        /// <summary>
        /// 更新MEM任务信息
        /// </summary>
        private bool StackMemTaskInfo(string contNum, string curNum, string toNum, string toNum2, string num)
        {
            try
            {
                string setQueue = "MEMQueue";
                string groupName = $"MEM.TC{num}_INFO";

                GZ.Modular.Redis.WriteGroupEntity group = new GZ.Modular.Redis.WriteGroupEntity
                {
                    groupName = groupName,
                    queueStatus = 1,
                    queueTime = DateTime.Now,
                    writeList = new System.Collections.Generic.List<GZ.Modular.Redis.ParamData>
                    {
                        new GZ.Modular.Redis.ParamData { paramName = $"MEM.TC{num}_Cont", paramValue = contNum },
                        new GZ.Modular.Redis.ParamData { paramName = $"MEM.TC{num}_CurPos", paramValue = curNum },
                        new GZ.Modular.Redis.ParamData { paramName = $"MEM.TC{num}_ToPos", paramValue = toNum },
                        new GZ.Modular.Redis.ParamData { paramName = $"MEM.TC{num}_ToPos2", paramValue = toNum2 }
                    }
                };

                return Conn.HYRedis.SetQueue(group, setQueue, "", "");
            }
            catch (Exception ex)
            {
                Conn.HYLog.Error(1, "更新MEM任务信息失败", 1, ex.ToString());
                return false;
            }
        }
    }
}